<template>
    <ClientOnly>
        <popup
            :show="visible"
            width="540px"
            title="知识库检索配置"
            @close="emits('close')"
            @confirm="emits('confirm', configs)"
        >
            <div class="py-4 px-8">
                <el-form-item label="搜索模式">
                    <el-select v-model="configs.mode" size="large" class="!w-[220px]">
                        <template #prefix>
                            <div class="flex items-center">
                                <el-image
                                    class="w-[16px] h-[16px] mr-1.5"
                                    :src="searchModeLists[searchModelDict[configs.mode]].icon"
                                />
                            </div>
                        </template>
                        <el-option
                            v-for="(item, index) in searchModeLists"
                            :key="index"
                            :label="item.name"
                            :value="item.key"
                        >
                            <div class="flex items-center">
                                <el-image class="w-[16px] h-[16px] mr-2" :src="item.icon" />
                                <span>{{ item.name }}</span>
                                <el-tooltip
                                    effect="dark"
                                    :content="item.tips"
                                    placement="top"
                                >
                                    <icon name="el-icon-InfoFilled" class="ml-2" />
                                </el-tooltip>
                            </div>
                        </el-option>
                    </el-select>
                </el-form-item>
                <el-form-item label="引用上限" prop="tokens">
                    <template #label>
                        <span class="mr-1">引用上限</span>
                        <el-tooltip effect="dark" placement="top">
                            <icon name="el-icon-InfoFilled" />
                            <template #content>
                                <p>该参数表示单次文档从知识库检索最大的Tokens数量</p>
                                <p>说明: 引用越多意味着所需消耗的token越多</p>
                                <p>注意: 切记不要超出模型的最大token限制</p>
                            </template>
                        </el-tooltip>
                    </template>
                    <div class="w-[95%] mb-4">
                        <el-slider
                            v-model="configs.tokens"
                            :min="100"
                            :max="30000"
                            :step="100"
                            show-input
                        />
                    </div>
                </el-form-item>
                <el-form-item label="最低相似度" prop="similar">
                    <template #label>
                        <span class="mr-1">最低相似度</span>
                        <el-tooltip effect="dark" placement="top">
                            <icon name="el-icon-InfoFilled" />
                            <template #content>
                                <p>语义检索的精度，提问检索的内容需要达到该精度才会被引用</p>
                                <br />
                                <p>1. 高语义相似度(>=0.8): 会检索相关性高的知识，会更准确，同时也容易未命中。</p>
                                <p>2. 低语义相似度(如0.4): 检索范围更大，更容易匹配知识，但可能回答会不准确。</p>
                                <p>3. 不同的向量模型检索相似度不一样，具体情况到 『知识库 - 搜索测试』进行调试。</p>
                            </template>
                        </el-tooltip>
                    </template>
                    <div class="w-[95%] mb-4">
                        <el-slider
                            v-model="configs.similar"
                            :min="0"
                            :max="1"
                            :step="0.001"
                            show-input
                        />
                    </div>
                </el-form-item>

                <el-form-item label="附件相似度" prop="annex_similar">
                    <template #label>
                        <span class="mr-1">附件相似度</span>
                        <el-tooltip effect="dark" placement="top">
                            <icon name="el-icon-InfoFilled" />
                            <template #content>
                                <p>附件检索的精度，提问检索的附件需要达到该精度才会被引用</p>
                                <br />
                                <p>1. 根据被已引用的数据基础上，再根据语义精度决定是否要引出附带的图片等附件。</p>
                                <p>2. 注意: 如果相似度设置过低，可能会把所有引用到的内容里的附件都显示出来。</p>
                                <p>3. 建议: 设置合适的相似度，并且在上传附件时填写合理的附件描述来提升精度。</p>
                            </template>
                        </el-tooltip>
                    </template>
                    <div class="w-[95%] mb-4">
                        <el-slider
                            v-model="configs.annex_similar"
                            :min="0"
                            :max="1"
                            :step="0.001"
                            show-input
                        />
                    </div>
                </el-form-item>

                <el-divider />

                <el-form-item label="结果重排">
                    <template #label>
                        <span class="mr-1">结果重排</span>
                        <el-tooltip effect="dark" placement="top">
                            <icon name="el-icon-InfoFilled" />
                            <template #content>
                                <p>使用重排模型来进行二次排序, 可增强综合排名。</p>
                            </template>
                        </el-tooltip>
                    </template>
                    <el-switch
                        v-model="configs.ranking"
                        size="large"
                        :active-value="1"
                        :inactive-value="0"
                    />
                </el-form-item>
                <template v-if="configs.ranking">
                    <el-form-item label="重排权重" prop="similar">
                        <div class="w-[95%]">
                            <el-slider
                                v-model="configs.ranking_score"
                                :min="0"
                                :max="1"
                                :step="0.001"
                                show-input
                            />
                        </div>
                    </el-form-item>
                    <el-form-item label="重排模型" prop="ranking_model">
                        <div class="w-[95%]">
                            <models-select
                                v-model="configs.ranking_model"
                                type="ranking"
                            />
                        </div>
                    </el-form-item>
                </template>

                <el-divider />

                <el-form-item label="问题优化">
                    <template #label>
                        <span class="mr-1">问题优化</span>
                        <el-tooltip effect="dark" placement="top">
                            <icon name="el-icon-InfoFilled" />
                            <template #content>
                                <p>综合历史记录和问题, 多维度的生成相似问题, 可增加知识库检索时的精准度。</p>
                            </template>
                        </el-tooltip>
                    </template>
                    <el-switch
                        v-model="configs.optimize"
                        size="large"
                        :active-value="1"
                        :inactive-value="0"
                    />
                </el-form-item>
                <el-form-item v-if="configs.optimize" label="优化模型" prop="optimize_model">
                    <div class="w-[95%]">
                        <models-select
                            v-model="configs.optimize_model"
                            type="chat"
                        />
                    </div>
                </el-form-item>
            </div>
        </popup>
    </ClientOnly>
</template>

<script setup lang="ts">
import semsIcon from '~/assets/image/search_semantics.png'
import fullIcon from '~/assets/image/search_full.png'
import mixIcon from '~/assets/image/search_mix.png'

const emits = defineEmits(['confirm', 'close'])
const props = defineProps({
    // 显示弹窗
    show: {
        type: Boolean,
        default: false
    },
    // 检索模式: [similar=语义, full=全文, mix=混合]
    mode: {
        type: String,
        default: 'similar'
    },
    // 引用上限
    tokens: {
        type: Number,
        default: 5000
    },
    // 相似度值
    similar: {
        type: Number,
        default: 0.4
    },
    // 检索重排: [0=否, 1=是]
    ranking: {
        type: Number,
        default: 0
    },
    // 问题优化: [0=否, 1=是]
    optimize: {
        type: Number,
        default: 0
    },
    // 附件相似度
    annexSimilar: {
        type: Number,
        default: 0.4
    },
    // 重排分数
    rankingScore: {
        type: Number,
        default: 0.5
    },
    // 重排模型
    rankingModel: {
        type: String,
        default: ''
    },
    // 问题优化
    optimizeModel: {
        type: String,
        default: ''
    }
})

const searchModelDict: any = {'similar': 0, 'full': 1, 'mix': 2}
const searchModeLists = [
    {
        key: 'similar',
        name: '语义检索',
        tips: '使用向量进行文本相关查询',
        icon: semsIcon,
    },
    {
        key: 'full',
        name: '全文检索',
        tips: '使用传统的全文检索, 适合查找一些关键词和主谓语特殊的数据',
        icon: fullIcon,
    },
    {
        key: 'mix',
        name: '混合检索',
        tips: '使用向量检索与全文检索的综合结果并重新进行排序',
        icon: mixIcon
    }
]

const visible = ref<boolean>(false)
const configs = reactive({
    mode: 'similar',
    tokens: 100,
    similar: 0.4,
    ranking: 0,
    optimize: 0,
    annex_similar: 0.4,
    ranking_score: 0.5,
    ranking_model: '',
    optimize_model: '',
})

watch(
    () => props.show,
    (val) => {
        visible.value = val
        if (val) {
            configs.mode = props.mode
            configs.tokens = props.tokens
            configs.similar = props.similar
            configs.ranking = props.ranking
            configs.optimize = props.optimize
            configs.annex_similar = props.annexSimilar
            configs.ranking_score = props.rankingScore
            configs.ranking_model = props.rankingModel
            configs.optimize_model = props.optimizeModel
        }
    }
)
</script>
